/*
 *  Project:            timelyRV_v1.4.x -- a RISCV-32IMC SoC.
 *  Module name:        Testbench.
 *  Description:        Testbench of timelyRV_SoC_hardware.
 *  Last updated date:  2022.10.10.
 *
 *  Copyright (C) 2021-2022 Junnan Li <lijunnan@nudt.edu.cn>.
 *  Copyright and related rights are licensed under the MIT license.
 *
 */

`timescale 1ns/1ps
module Testbench(
);

`ifdef DUMP_FSDB
  initial begin
    $fsdbDumpfile("wave.fsdb");
    $fsdbDumpvars(0);
    $fsdbDumpMDA();
    $vcdpluson;
    $vcdplusmemon;
  end
`endif
  reg                   clk,rst_n;



  initial begin
    clk = 0;
    forever #1 clk = ~clk;
  end

  initial begin
    rst_n = 1;
    #2  rst_n = 0;
    #10 rst_n = 1;
  end


  initial begin
    #2000 $finish;
  end
  reg                 r_rst_n;

  reg   [3:0]         r_icache_req;
  reg   [3:0][31:0]   r_icache_addr;
  wire  [3:0][31:0]   w_icache_rdata;
  wire  [3:0]         w_icache_rvalid;
  wire  [3:0]         w_icache_gnt;

  wire                w_mm_rden;
  wire  [31:0]        w_mm_addr;
  reg   [127:0]       r_mm_rdata;
  reg                 r_mm_rvalid;
  reg                 r_mm_gnt;


  iCache_Top icache_top(
    .i_clk            (clk),
    .i_rst_n          (r_rst_n),
    .i_icache_req     (r_icache_req),
    .i_icache_addr    (r_icache_addr),
    .o_icache_rdata   (w_icache_rdata),
    .o_icache_rvalid  (w_icache_rvalid),
    .o_icache_gnt     (w_icache_gnt),
    .o_mm_rden        (w_mm_rden),
    .o_mm_addr        (w_mm_addr),
    .i_mm_rdata       (r_mm_rdata),
    .i_mm_rvalid      (r_mm_rvalid),
    .i_mm_gnt         (r_mm_gnt)
  );

  // initial begin
  //   icache_top.icache_update.r_lock_gnt = 4'hf;
  // end


  reg [3:0] r_clk_cnt;
  always_ff @(posedge clk or negedge rst_n) begin
    if (~rst_n) begin
      r_rst_n                       <= 1'b1;
      r_clk_cnt                     <= 4'b0;
    end else begin
      r_clk_cnt                     <= 4'd1 + r_clk_cnt;
      if(r_clk_cnt[3] == 1'b1)
        r_clk_cnt                   <= r_clk_cnt;
      r_rst_n                       <= r_clk_cnt[3];
    end
  end

  integer i;
  reg        r_temp_mm_rden;
  reg [31:0] r_temp_mm_addr;
  always_ff @(posedge clk or negedge r_rst_n) begin
    if (~r_rst_n) begin
      r_icache_req                  <= 'b0;
      r_icache_addr                 <= 'b0;
      r_mm_rdata                    <= 'b0;
      r_mm_rvalid                   <= 'b0;
      r_mm_gnt                      <= 1'b1;
    end else begin
      for(i=0; i<4; i=i+1) begin
        if(w_icache_gnt[i] == 1'b1) begin
          r_icache_req[i]           <= 1'b1;
          r_icache_addr[i]          <= (r_icache_addr[i] + 32'd1) | i<<8;
        end
        if(r_icache_addr[i][7:0] == 8'hff)
          r_icache_addr[i]          <= 'b0;
      end

      r_mm_rvalid                   <= 1'b0;
      r_temp_mm_rden                <= w_mm_rden;
      r_temp_mm_addr                <= w_mm_addr;
      if(r_temp_mm_rden == 1'b1) begin
        r_mm_rvalid                 <= 1'b1;
        r_mm_rdata                  <= {r_temp_mm_addr+32'd3,r_temp_mm_addr+32'd2,r_temp_mm_addr+32'd1,r_temp_mm_addr};
      end
    end
  end


endmodule